package org.zhaya.sdk.util;

import cn.hutool.core.date.DateUtil;
import com.github.mustachejava.Mustache;
import com.github.mustachejava.MustacheFactory;
import com.google.common.collect.Lists;
import io.logz.sawmill.Doc;
import io.logz.sawmill.Template;
import io.logz.sawmill.exceptions.SawmillException;
import io.logz.sawmill.mustache.factories.UnescapedMustacheFactory;
import io.logz.sawmill.mustache.factories.UnescapedWithJsonStringMustacheFactory;
import org.apache.commons.lang3.StringUtils;

import java.io.StringReader;
import java.io.StringWriter;
import java.util.LinkedHashMap;
import java.util.Objects;


public class BdpTemplateService {
    /**
     * remove backward compatibility mustache and support only json string implementation
     */
    public static final String JSON_STRING_SUFFIX = "_sawmill_json";
    private final MustacheFactory mustacheFactory;
    private final UnescapedWithJsonStringMustacheFactory jsonStringMustacheFactory;
    public static final String DODP_NOW_STRING = "{{Date}} {{time}}";

    public BdpTemplateService() {
        this.mustacheFactory = new UnescapedMustacheFactory();
        this.jsonStringMustacheFactory = new UnescapedWithJsonStringMustacheFactory();
    }

    public Template createTemplate(String template) {
        if (Objects.isNull(template)) {
            throw new SawmillException("template cannot be with null value");
        }

        if (template.equals(DODP_NOW_STRING) || !template.contains("{{") && template.contains("}}")) {
            return new StringTemplate(template);
        }

        Mustache mustache = template.contains(JSON_STRING_SUFFIX) ?
                jsonStringMustacheFactory.compile(new StringReader(template.replaceAll(JSON_STRING_SUFFIX, StringUtils.EMPTY)), StringUtils.EMPTY) :
                mustacheFactory.compile(new StringReader(template), StringUtils.EMPTY);

        return new MustacheTemplate(mustache);
    }

    public static class StringTemplate implements Template {
        private final String value;

        private StringTemplate(String value) {
            this.value = value;
        }

        @Override
        public String render(Doc doc) {
            if (value.equals(DODP_NOW_STRING)) {
                return DateUtil.now();
            }
            return value;
        }
    }

    public static class MustacheTemplate implements Template {
        private final Mustache mustache;
        private static final DateTemplateHandler DATE_TEMPLATE_HANDLER = new DateTemplateHandler();

        private MustacheTemplate(Mustache value) {
            this.mustache = value;
        }

        @Override
        public String render(Doc doc) {
            Object docContext;
            if (Objects.isNull(doc)) {
                docContext = new LinkedHashMap<>();
            } else {
                docContext = doc.getSource();
            }

            StringWriter writer = new StringWriter();
            mustache.execute(writer, Lists.newArrayList(docContext, DATE_TEMPLATE_HANDLER));

            writer.flush();

            return writer.toString();
        }

    }
}